package com.lkl.utils;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.lkl.Condition;
import com.lkl.Menu;
import com.lkl.entity.Address;
import com.lkl.entity.AddressVO;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据处理类
 * 全国数据处理
 */
public class DataNewUtil {

    /**
     * 全局结果集
     */
    private static List<AddressVO> resultList = new ArrayList<>();
    /**
     * 县级数据集
     */
    private static final Map<String, AddressVO> level3Map = new HashMap<>();
    /**
     * 乡级数据集
     */
    private static final Map<String, AddressVO> level4Map = new HashMap<>();
    private static final String path = FileUtils.filePath + "/全国行政区划数据";

    /**
     * 处理全国三级数据
     * 省-地-县
     * @param data
     */
    public static void toTreeJsonBy3(List<Address> data) {
        System.out.println("====> 开始处理全国三级数据");
        System.out.println("====> 数据条数：" + data.size());
        DateTime start = new DateTime();
        System.out.println("====> 开始时间：" + start);
        //存入临时数据
        HashMap<String, AddressVO> map = new HashMap<>();
        List<AddressVO> list = new ArrayList<>();
        data.forEach(address -> {
            AddressVO addressVO = new AddressVO(address.getCode(), address.getName(), address.getParentCode());
            map.put(addressVO.getCode(), addressVO);
            list.add(addressVO);
            //不存在8个0的数据，为县级数据，存入map
            if (!address.getCode().contains(StringUtils.rightPad("", 8, '0'))) {
                level3Map.put(addressVO.getCode(), addressVO);
            }
            //特殊地区，只有四级划分，没有县级划分
            // 东莞
            //中山
            //儋州市
            if (addressVO.getCode().equals("441900000000")
                    || addressVO.getCode().equals("442000000000")
                    || addressVO.getCode().equals("460400000000")) {
                level3Map.put(addressVO.getCode(), addressVO);
            }

        });
        //处理数据，转换为树结果集
        for (AddressVO addressVO : list) {
            //获取父对象：
            AddressVO parent = map.get(addressVO.getParentCode());
            //父对象不为空，当前对象存入子集
            if (null != parent) {
                //判断子集是否初始化
                if (null == parent.getChildren()) {
                    parent.setChildren(new ArrayList<>());
                }
                parent.getChildren().add(addressVO);
            } else {
                //当前对象为父对象，存入结果集
                resultList.add(addressVO);
            }
        }
        // 全国/三级/全国-省-地-县-三级.json
        String url = DataNewUtil.path + "/三级/全国-省-地-县-三级.json";
        List<String> result = new ArrayList<>();
        result.add(JSONObject.toJSONString(resultList));
        //写入数据
        FileUtil.writeLines(result, url, CharsetUtil.CHARSET_UTF_8, false);
        Menu.continuaFlag = true;
    }

    /**
     * 处理全国四级数据
     *
     * @param data 乡级数据
     */
    public static void toTreeJsonBy4(List<Address> data) {
        System.out.println("====> 开始处理乡级数据");
        System.out.println("====> 数据条数：" + data.size());
        DateTime start = new DateTime();
        System.out.println("====> 开始时间：" + start);
        List<AddressVO> list = new ArrayList<>();
        //异常数据
        List<AddressVO> errorDataList = new ArrayList<>();
        data.forEach(address -> {
            AddressVO addressVO = new AddressVO(address.getCode(), address.getName(), address.getParentCode());
            //存入乡级结果集
            level4Map.put(addressVO.getCode(), addressVO);
            list.add(addressVO);
            if (addressVO.getCode().equals("110105001000")
                    ||addressVO.getCode().equals("110102007000")
                    ||addressVO.getCode().equals("110101005000")
                    ||addressVO.getCode().equals("110105003000")
                    ||addressVO.getCode().equals("110101004000")) {
                System.out.println("存进去了");
            }
        });
        //处理数据，转换为树结果集
        for (AddressVO addressVO : list) {
            //获取县级父对象：
            AddressVO parent = level3Map.get(addressVO.getParentCode());
            //父对象不为空，当前对象存入子集
            if (null != parent) {
                //判断子集是否初始化
                if (null == parent.getChildren()) {
                    parent.setChildren(new ArrayList<>());
                }
                parent.getChildren().add(addressVO);
            } else {
                //为空，异常数据，存入到异常数据集
                errorDataList.add(addressVO);
            }
        }
        // 全国/三级/全国-省-地-县-三级.json
        StringBuilder url = new StringBuilder();
        url.append(DataNewUtil.path)
                .append("/四级/全国-省-地-县-乡-四级.json");
        List<String> result = new ArrayList<>();
        result.add(JSONObject.toJSONString(resultList));
        //写入数据
        FileUtil.writeLines(result, url.toString(), CharsetUtil.CHARSET_UTF_8, false);
        //获取结果集的子数据
        resultList.forEach(addressVO1 -> {
            //去除数据
            result.clear();
            //将子数据转换为json
            result.add(JSONObject.toJSONString(addressVO1.getChildren()));
            //重置路径为.../全国数据/
            url.setLength(url.indexOf("据/") + 2);
            //全国数据/北京市/三级/北京市-地-县-乡-三级.json
            url.append("/省级数据/")
            .append(addressVO1.getName())
                    .append("/三级/")
                    .append(addressVO1.getName())
                    .append("-地-县-乡-三级.json");
            //写入数据
            FileUtil.writeLines(result, url.toString(), CharsetUtil.CHARSET_UTF_8, false);
        });
        System.out.println("<==== 处理乡级数据结束");
        if (errorDataList.size() > 0) {
            //写入错误日志
            String logUrl = FileUtils.filePath + "/log/error.text";
            FileUtil.writeString("全国四级处理异常数据",logUrl,CharsetUtil.CHARSET_UTF_8);
            FileUtil.writeLines(errorDataList, logUrl, CharsetUtil.CHARSET_UTF_8, true);
            System.out.println("================> 错误信息：");
//            System.out.println(errorDataList);
            System.out.println("数据条数：" + errorDataList.size() );
            System.out.println("<================ 错误信息：");
        }
        DateTime end = new DateTime();
        System.out.println("<==== 结束时间：" + end);
        System.out.println("<==== 花费时间：" + end.between(end));
        Menu.continuaFlag = true;
    }

    /**
     * 处理全国五级数据
     *
     * @param data 村级数据
     */
    public static void toTreeJsonBy5(List<Address> data) {
        System.out.println("====> 开始处理村级数据");
        System.out.println("====> 数据条数：" + data.size());
        DateTime start = new DateTime();
        System.out.println("====> 开始时间：" + start);
        //村级数据
        List<AddressVO> list = new ArrayList<>();
        //异常数据
        List<AddressVO> errorDataList = new ArrayList<>();
        data.forEach(address -> {
            AddressVO addressVO = new AddressVO(address.getCode(), address.getName(), address.getParentCode());
            list.add(addressVO);
        });
        //处理数据，转换为树结果集
        for (AddressVO addressVO : list) {
            //获取乡级父对象：
            AddressVO parent = level4Map.get(addressVO.getParentCode());
            //父对象不为空，当前对象存入子集
            if (null != parent) {
                //判断子集是否初始化
                if (null == parent.getChildren()) {
                    parent.setChildren(new ArrayList<>());
                }
                parent.getChildren().add(addressVO);
            } else {
                //为空，异常数据，存入到异常数据集
                errorDataList.add(addressVO);
            }
        }
        // 全国/五级/全国-省-地-县-乡-村-五级.json
        StringBuilder url = new StringBuilder();
        url.append(DataNewUtil.path)
                .append("/五级/全国-省-地-县-乡-村-五级.json");
        List<String> result = new ArrayList<>();
        result.add(JSONObject.toJSONString(resultList));
        //写入数据
        FileUtil.writeLines(result, url.toString(), CharsetUtil.CHARSET_UTF_8, false);
        //获取结果集的子数据，addressVO1为省级
        resultList.forEach(addressVO1 -> {
            //处理省级数据。获取省级四级数据
            //去除数据
            result.clear();
            //将子数据转换为json
            result.add(JSONObject.toJSONString(addressVO1.getChildren()));
            //重置路径为.../全国数据/
            url.setLength(url.indexOf("据/") + 2);
            //全国数据/北京市/四级/北京市-地-县-乡-村-四级.json
            url.append("/省级数据/")
                    .append(addressVO1.getName())
                    .append("/四级/")
                    .append(addressVO1.getName())
                    .append("-地-县-乡-村-四级.json");
            //写入数据
            FileUtil.writeLines(result, url.toString(), CharsetUtil.CHARSET_UTF_8, false);
            //遍历子数据 地-县-乡，addressVO2：地集
            addressVO1.getChildren().forEach(addressVO2 -> {
                //获取县-乡-村三级数据，数据级别：
                //去除数据
                result.clear();
                //将子数据转换为json
                result.add(JSONObject.toJSONString(addressVO2.getChildren()));
                //重置路径为.../全国数据/
                url.setLength(url.indexOf("据/") + 2);
                //全国数据/北京市/地级数据/北京市-市辖区-县-乡-村-三级.json
                url.append("/省级数据/")
                        .append(addressVO1.getName())
                        .append("/地级数据/")
                        .append(addressVO1.getName())
                        .append("-")
                        .append(addressVO2.getName())
                        .append("-县-乡-村-三级.json");
                //写入数据
                FileUtil.writeLines(result, url.toString(), CharsetUtil.CHARSET_UTF_8, false);
            });
        });
        System.out.println("<==== 处理村级数据结束");
        if (errorDataList.size() > 0) {
            //写入错误日志
            String logUrl = FileUtils.filePath + "/log/error.text";
            FileUtil.writeLines(errorDataList, logUrl, CharsetUtil.CHARSET_UTF_8, true);
            System.out.println("================> 错误信息：");
            System.out.println(errorDataList);
            System.out.println("<================ 错误信息：");
        }
        DateTime end = new DateTime();
        System.out.println("<==== 结束时间：" + end);
        System.out.println("<==== 花费时间：" + end.between(end));
        Menu.continuaFlag = true;
    }

    public static void toTreeJson(List<Address> data, Condition condition) {
        System.err.println("开始处理数据");
        System.err.println("===> 数据条数" + data.size());
        System.err.println("===> 条件" + condition);
        //记录开始时间
        DateTime start = new DateTime();
        //定义结果集合
        List<AddressVO> resultList = new ArrayList<>();
        List<AddressVO> list = new ArrayList<>();
        //将所有数据存入map
        Map<String, AddressVO> map = new HashMap<>(data.size());
        data.forEach(address -> {
            AddressVO addressVO = new AddressVO(address.getCode(), address.getName(), address.getParentCode());
            map.put(address.getCode(), addressVO);
            list.add(addressVO);
        });
        long count = 1L;
        for (AddressVO address : list) {
            //获取父对象
            AddressVO addressVO = map.get(address.getParentCode());
            //不为null,为子对象
            if (addressVO != null) {
                if (null == addressVO.getChildren()) {
                    addressVO.setChildren(new ArrayList<>());
                }
                addressVO.getChildren().add(address);
            } else {
                //为父对象
                resultList.add(address);
            }
            count++;
        }
        toRoot(condition, resultList);
        //有四级，处理子数据
        if ("四级".equals(condition.getLevel())) {
            toCity(condition, resultList);
        }
        System.err.println("《===== 处理数据" + list.size() + "条");
        System.err.println("《===== 根结点" + resultList.size() + "个");
        map.clear();
        list.clear();
        data.clear();
        System.err.println("《===== " + condition.getProvince() + "数据转换已完成");
    }

    /**
     * 适用于省级数据处理
     *
     * @param condition
     * @param resultList
     */
    private static void toRoot(Condition condition, List<AddressVO> resultList) {
        //路径为 /北京/三级/省份-级别.json
        StringBuilder path = new StringBuilder();
        //默认为三级
        String level = "市-区-镇-";
        //根据条件判断是否修改
        if ("四级".equals(condition.getLevel())) {
            level = "市-区-镇-村-";
        }
        path.append(FileUtils.filePath)
                .append("/")
                .append(condition.getProvince())
                .append("/")
                .append(condition.getLevel())
                .append("/")
                .append(condition.getProvince())
                .append("-")
                .append(level)
                .append(condition.getLevel())
                .append(".json");
        System.out.println("文件路径：" + path);
        List<String> collect1 = new ArrayList<>();
        //获取子数据并转换为json
        collect1.add(JSONObject.toJSONString(resultList.get(0).getChildren(), SerializerFeature.WriteMapNullValue));
        FileUtil.writeLines(collect1, path.toString(), CharsetUtil.CHARSET_UTF_8);
    }

    /**
     * 处理市区数据
     * 只有三级
     * 区-镇-村
     *
     * @param condition
     * @param resultList
     */
    private static void toCity(Condition condition, List<AddressVO> resultList) {
        //获取所有城市级别的数据
        List<AddressVO> data = resultList.get(0).getChildren();
        System.err.println("《===== 处理子数据" + data.size() + "条");
        //路径为 /北京/三级/省份-级别.json
        StringBuilder path = new StringBuilder();
        //默认为三级
        String level = "-区-镇-村-三级.json";
        data.forEach(address -> {
            //根据条件判断是否修改
            path.append(FileUtils.filePath)
                    .append("/")
                    .append(condition.getProvince())  //北京市
                    .append("/")                      // /
                    .append(condition.getProvince())  // 北京市
                    .append("城市数据/")               // 城市数据/
                    .append(address.getName())       //  市辖区
                    .append(level);                 // -区-镇-村-三级.json
            System.out.println("文件路径：" + path);
            List<String> collect1 = new ArrayList<>();
            //获取子数据并转换为json
            collect1.add(JSONObject.toJSONString(address.getChildren(), SerializerFeature.WriteMapNullValue));
            FileUtil.writeLines(collect1, path.toString(), CharsetUtil.CHARSET_UTF_8);
            //设置路径为0
            path.setLength(0);
        });
        System.err.println("《===== 处理子数据完成！");
    }
}
